<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>模块管理</title>
    <!-- <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
      crossorigin="anonymous"
    /> -->
    <!-- Import all the bootstrap css files from css folder -->
    <link rel="stylesheet" href="css/styles.css" />
    <link rel="stylesheet" href="css/bootstrap.min.css" />

    <!-- Logo -->
    <link rel="simpleadmin-logo" href="favicon.ico" />

    <!--  Import BootStrap Javascript -->
    <script src="js/bootstrap.bundle.min.js"></script>
    <script src="js/alpinejs.min.js" defer></script>
  </head>
  <body>
    <main>
      <div class="container my-4" x-data="processAllInfos()">
        <nav class="navbar navbar-expand-lg mt-2">
          <div class="container-fluid">
            <a class="navbar-brand" href="/"
              ><span class="mb-0 h4 fw-bold">模块管理</span></a>
            <button
              class="navbar-toggler"
              type="button"
              data-bs-toggle="collapse"
              data-bs-target="#navbarText"
              aria-controls="navbarText"
              aria-expanded="false"
              aria-label="Toggle navigation"
            >
              <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarText">
              <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                 <li class="nav-item">
                 <a class="nav-link active" aria-current="page" href="/">首页</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="network.html">网络</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/scanner.html">扫描</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/settings.html">设置</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/sms.html">短信</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/console">控制台</a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/deviceinfo.html"
                    >设备信息</a
                  >
                </li>
              </ul>
              <span class="navbar-text">
                <button class="btn btn-link text-reset" id="darkModeToggle">
                  Dark Mode
                </button>
              </span>
            </div>
          </div>
        </nav>

        <div class="row align-items-center mt-5 gap-md-3 gap-2">
          <div class="col align-self-center">
            <div class="card">
              <div
                class="card-body d-flex flex-column align-items-center justify-content-center"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 320 512"
                  height="85"
                  width="85"
                >
                  <path
                    fill="#fdb53c"
                    d="M160 64c-26.5 0-48 21.5-48 48V276.5c0 17.3-7.1 31.9-15.3 42.5C86.2 332.6 80 349.5 80 368c0 44.2 35.8 80 80 80s80-35.8 80-80c0-18.5-6.2-35.4-16.7-48.9c-8.2-10.6-15.3-25.2-15.3-42.5V112c0-26.5-21.5-48-48-48zM48 112C48 50.2 98.1 0 160 0s112 50.1 112 112V276.5c0 .1 .1 .3 .2 .6c.2 .6 .8 1.6 1.7 2.8c18.9 24.4 30.1 55 30.1 88.1c0 79.5-64.5 144-144 144S16 447.5 16 368c0-33.2 11.2-63.8 30.1-88.1c.9-1.2 1.5-2.2 1.7-2.8c.1-.3 .2-.5 .2-.6V112zM208 368c0 26.5-21.5 48-48 48s-48-21.5-48-48c0-20.9 13.4-38.7 32-45.3V272c0-8.8 7.2-16 16-16s16 7.2 16 16v50.7c18.6 6.6 32 24.4 32 45.3z"
                  />
                </svg>
                <h1
                  class="card-text mt-4"
                  x-text="temperature + ' &deg;C'"
                ></h1>
              </div>
              <div class="card-footer"
              style="text-align:center;">
              模块温度</div>
            </div>
          </div>

          <div class="col align-self-center">
            <div class="card">
              <div
                class="card-body d-flex flex-column align-items-center justify-content-center"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 384 512"
                  height="85"
                  width="85"
                >
                  <path
                    fill="#6a46d8"
                    d="M64 0H242.7c17 0 33.3 6.7 45.3 18.7L365.3 96c12 12 18.7 28.3 18.7 45.3V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64C0 28.7 28.7 0 64 0zM96 192c-17.7 0-32 14.3-32 32v32h64V192H96zM64 352h80 96 80V288H240 144 64v64zM320 224c0-17.7-14.3-32-32-32H256v64h64V224zM160 192v64h64V192H160zM288 448c17.7 0 32-14.3 32-32V384H256v64h32zM160 384v64h64V384H160zM64 416c0 17.7 14.3 32 32 32h32V384H64v32z"
                  />
                </svg>
                <h1 class="card-text mt-4" x-text="simStatus"></h1>
              </div>
              <div class="card-footer"
              style="text-align:center;">
              SIM卡状态</div>
            </div>
          </div>

          <div class="col align-self-center">
            <div class="card">
              <div
                class="card-body d-flex flex-column align-items-center justify-content-center"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 640 512"
                  height="85"
                  width="85"
                >
                  <path
                    fill="#2fa7fb"
                    d="M576 0c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V32c0-17.7 14.3-32 32-32zM448 96c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V128c0-17.7 14.3-32 32-32zM352 224V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V224c0-17.7 14.3-32 32-32s32 14.3 32 32zM192 288c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V320c0-17.7 14.3-32 32-32zM96 416v64c0 17.7-14.3 32-32 32s-32-14.3-32-32V416c0-17.7 14.3-32 32-32s32 14.3 32 32z"
                  />
                </svg>
                <h1 class="card-text mt-4" x-text="signalPercentage + '%'"></h1>
              </div>
              <div class="card-footer"
              style="text-align:center;">
              信号强度</div>
            </div>
          </div>

          <div class="col align-self-center">
            <div class="card">
              <div
                class="card-body d-flex flex-column align-items-center justify-content-center"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 640 512"
                  height="85"
                  width="85"
                >
                  <path
                    fill="#20c0ae"
                    d="M0 336c0 79.5 64.5 144 144 144H512c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z"
                  />
                </svg>
                <h1
                  class="card-text mt-4"
                  x-text="internetConnectionStatus"
                ></h1>
              </div>
              <div class="card-footer"
              style="text-align:center;">
              网络状态</div>
            </div>
          </div>
        </div>

        <div class="row mt-5 gap-3">
          <div class="col">
            <div class="card">
              <div class="card-header">网络信息</div>
              <div class="card-body">
                <div class="card-text table-responsive-sm">
                  <table class="table">
              <style>.table th,.table td {  white-space: nowrap; /* 防止换行 */}</style>
                    <tbody>
                      <tr>
                        <th scope="row">SIM卡</th>
                        <td x-text="activeSim"></td>
                      </tr>
                      <tr>
                        <th scope="row">运营商</th>
                        <td x-text="networkProvider"></td>
                      </tr>
                      <tr>
                        <th scope="row">运营商代码</th>
                        <td x-text="mccmnc"></td>
                      </tr>
                      <tr>
                        <th scope="row">接入点APN</th>
                        <td x-text="apn"></td>
                      </tr>
                      <tr>
                        <th scope="row">签约速率Mbps</th>
                        <td x-text="ambr"></td>
                      </tr>
                      <tr>
                        <th scope="row">网络模式</th>
                        <td x-text="networkMode"></td>
                      </tr>
                      <tr>
                        <th scope="row">频段</th>
                        <td x-text="bands"></td>
                      </tr>
                      <tr>
                        <th scope="row">带宽</th>
                        <td x-text="bandwidth"></td>
                      </tr>
                      <tr>
                        <th scope="row">频点</th>
                        <td x-text="earfcns"></td>
                      </tr>
                      <tr>
                        <th scope="row">PCI</th>
                        <td
                          x-show="sccPCI != '-'"
                          x-text="pccPCI + ', ' + sccPCI"
                        ></td>
                        <td x-show="sccPCI == '-'" x-text="pccPCI"></td>
                      </tr>
                      <tr>
                        <th scope="row">IPv<sup>4</sup></th>
                        <td x-text="ipv4"></td>
                      </tr>
                      <tr>
                        <th scope="row">IPv<sup>6</sup></th>
                        <td x-text="ipv6"></td>
                      </tr>
                      <tr>
                        <th scope="row">在线时长</th>
                        <td x-text="uptime"></td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
              <div class="card-footer">
                <div class="row row-cols-2">
                  <div class="col">
                    <p class="btn">刷新率(>3s)</p>
                  </div>
                  <div class="col">
                    <div class="input-group">
                      <input
                        x-model="newRefreshRate"
                        class="form-control"
                        type="number"
                        min="3"
                        max="60"
                        x-bind:placeholder="refreshRate + 's'"
                      />
                      <button
                        @click="updateRefreshRate()"
                        class="btn btn-outline-secondary"
                        type="button"
                      >
                        设置
                      </button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class="col">
            <div class="card">
              <div class="card-header">信号</div>
              <div class="card-body">
                <div class="card-text table-responsive-sm">
                  <table class="table">
                    <tbody>
                      <tr>
                        <th scope="row">评估</th>
                        <td x-text="signalAssessment"></td>
                      </tr>
                      <tr>
                        <th scope="row">流量统计</th>
                        <td
                          x-text="downloadStat + ' 下载 / ' + uploadStat + ' 上传'"
                        ></td>
                      </tr>
                      <tr x-show="csq != 'NR-SA Mode'">
                        <th scope="row">CSQ</th>
                        <td x-show="csq != '-'" x-text="csq"></td>
                        <td x-show="csq == '-'" class="fst-italic">None</td>
                      </tr>
                      <tr>
                        <th scope="row">小区ID</th>
                        <td x-text="cellID"></td>
                      </tr>
                      <tr>
                        <th scope="row">eNB ID</th>
                        <td x-text="eNBID"></td>
                      </tr>
                      <tr>
                        <th scope="row">LAC ID</th>
                        <td x-text="tac"></td>
                      </tr>
                      <!-- <tr x-show="rssi != '-'">
                        <th scope="row">RSSI<sup>4G</sup></th>
                        <td x-show="rssi != '-'" x-text="rssi"></td>
                        <td x-show="rssi == '-'" class="fst-italic">None</td>
                      </tr> -->
                      <tr x-show="rsrqLTE != '-'">
                        <th scope="row">SS_RSRQ<sup>4G</sup></th>
                        <td
                          class="gap-4 align-items-center"
                          x-data="{ getProgressBarClass: function() {
                          // Remove the percentage sign and convert to integer
                          var percentage = parseInt(this.rsrqLTEPercentage);
                          
                          if (percentage >= 60) {
                              return 'progress-bar bg-success is-medium';
                          } else if (percentage >= 40) {
                              return 'progress-bar bg-warning is-warning is-medium';
                          } else {
                              return 'progress-bar bg-danger is-medium';
                          }
                      } }"
                        >
                          <div
                            x-show="rsrqLTE != '-' && rsrqLTEPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="RSRQ BAR"
                            :aria-valuenow="rsrqLTEPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + rsrqLTEPercentage + '%'"
                            >
                              <span
                                x-text="rsrqLTE + ' / ' +  rsrqLTEPercentage + '%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-show="rsrqLTEPercentage == '0'"
                            x-text="rsrqLTE"
                          ></span>
                          <span x-show="rsrqLTE == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                      <tr x-show="rsrqNR != '-'">
                        <th scope="row">SS_RSRQ<sup>5G</sup></th>
                        <td
                          x-data="{ getProgressBarClass: function() {
                          // Remove the percentage sign and convert to integer
                          var percentage = parseInt(this.rsrqNRPercentage);
                          
                          if (percentage >= 60) {
                              return 'progress-bar bg-success is-medium';
                          } else if (percentage >= 40) {
                              return 'progress-bar bg-warning is-warning is-medium';
                          } else {
                              return 'progress-bar bg-danger is-medium';
                          }
                      } }"
                        >
                          <div
                            x-show="rsrqNR != '-' && rsrqNRPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="RSRQ BAR"
                            :aria-valuenow="rsrqNRPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + rsrqNRPercentage + '%'"
                            >
                              <span
                                x-text="rsrqNR + ' / ' + rsrqNRPercentage + '%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-show="rsrqNRPercentage == '0'"
                            x-text="rsrqNR"
                          ></span>
                          <span x-show="rsrqNR == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                      <tr x-show="rsrpLTE != '-'">
                        <th scope="row">RSRP<sup>4G</sup></th>
                        <td
                          class="gap-4 align-items-center"
                          x-data="{
                          getProgressBarClass: function() {
                              // Remove the percentage sign and convert to integer
                              var percentage = parseInt(this.rsrpLTEPercentage);
                              
                              if (percentage >= 60) {
                                  return 'progress-bar bg-success is-medium';
                              } else if (percentage >= 40) {
                                  return 'progress-bar bg-warning is-warning is-medium';
                              } else {
                                  return 'progress-bar bg-danger is-medium';
                              }
                          }
                        }"
                        >
                          <div
                            x-show="rsrpLTE != '-' && rsrpLTEPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="RSRP BAR"
                            :aria-valuenow="rsrpLTEPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + rsrpLTEPercentage + '%'"
                            >
                              <span
                                x-text="rsrpLTE + ' / ' + rsrpLTEPercentage + '%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-show="rsrpLTEPercentage == '0'"
                            x-text="rsrpLTE"
                          ></span>
                          <span x-show="rsrpLTE == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                      <tr x-show="rsrpNR != '-'">
                        <th scope="row">SS_RSRP<sup>5G</sup></th>
                        <td
                          class="gap-4 align-items-center"
                          x-data="{
                          getProgressBarClass: function() {
                              // Remove the percentage sign and convert to integer
                              var percentage = parseInt(this.rsrpNRPercentage);
                              
                              if (percentage >= 60) {
                                  return 'progress-bar bg-success is-medium';
                              } else if (percentage >= 40) {
                                  return 'progress-bar bg-warning is-warning is-medium';
                              } else {
                                  return 'progress-bar bg-danger is-medium';
                              }
                          }
                        }"
                        >
                          <div
                            x-show="rsrpNR != '-' && rsrpNRPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="RSRP BAR"
                            :aria-valuenow="rsrpNRPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + rsrpNRPercentage + '%'"
                            >
                              <span
                                x-text="rsrpNR + ' / ' + rsrpNRPercentage + '%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-show="rsrpNRPercentage == '0'"
                            x-text="rsrpNR"
                          ></span>
                          <span x-show="rsrpNR == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                      <tr x-show="sinrLTE != '-'">
                        <th scope="row">SINR<sup>4G</sup></th>
                        <td
                          class="gap-4 align-items-center"
                          x-data="{
                          getProgressBarClass: function() {
                              // Remove the percentage sign and convert to integer
                              var percentage = parseInt(this.sinrLTEPercentage);
                              
                              if (percentage >= 60) {
                                  return 'progress-bar bg-success is-medium';
                              } else if (percentage >= 40) {
                                  return 'progress-bar bg-warning is-warning is-medium';
                              } else {
                                  return 'progress-bar bg-danger is-medium';
                              }
                          }
                        }"
                        >
                          <div
                            x-show="sinrLTE != '-' && sinrLTEPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="SINR BAR"
                            :aria-valuenow="sinrLTEPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + sinrLTEPercentage +'%'"
                            >
                              <span
                                x-text="sinrLTE + ' / ' + sinrLTEPercentage +'%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-text="sinrLTE"
                            x-show="sinrLTEPercentage == '0'"
                          ></span>
                          <span x-show="sinrLTE == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                      <tr x-show="sinrNR != '-'">
                        <th scope="row">SINR<sup>5G</sup></th>
                        <td
                          class="gap-4 align-items-center"
                          x-data="{
                          getProgressBarClass: function() {
                              // Remove the percentage sign and convert to integer
                              var percentage = parseInt(this.sinrNRPercentage);
                              
                              if (percentage >= 60) {
                                  return 'progress-bar bg-success is-medium';
                              } else if (percentage >= 40) {
                                  return 'progress-bar bg-warning is-warning is-medium';
                              } else {
                                  return 'progress-bar bg-danger is-medium';
                              }
                          }
                        }"
                        >
                          <div
                            x-show="sinrNR != '-' && sinrNRPercentage != '0'"
                            class="progress w-100"
                            role="progressbar"
                            aria-label="SINR BAR"
                            :aria-valuenow="sinrNRPercentage"
                            aria-valuemin="0"
                            aria-valuemax="100"
                            style="height: 18px"
                          >
                            <div
                              :class="getProgressBarClass()"
                              :style="'width: ' + sinrNRPercentage +'%'"
                            >
                              <span
                                x-text="sinrNR + ' / ' + sinrNRPercentage +'%'"
                              ></span>
                            </div>
                          </div>
                          <span
                            x-text="sinrNR"
                            x-show="sinrNRPercentage == '0'"
                          ></span>
                          <span x-show="sinrNR == '-'" class="fst-italic">
                            None
                          </span>
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
              <div class="card-footer">
                <div class="card-text">
                  <div class="row">
                    <div class="col">
                      <div>
                        <p>更新时间</p>
                      </div>
                    </div>

                    <div class="col">
                      <p x-text="lastUpdate"></p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
    <script src="js/dark-mode.js"></script>

    <script>
      function processAllInfos() {
        return {
          atcmd: "",
          internetConnectionStatus: "已断开",
          temperature: "0",
          simStatus: "无SIM卡",
          activeSim: "无SIM卡",
          networkProvider: "N/A",
          mccmnc: "00000",
          apn: "未知",
          networkMode: "已断开",
          bands: "未知",
          bandwidth: "未知",
          earfcns: "000",
          pccPCI: "0",
          sccPCI: "-",
          ipv4: "000.000.000.000",
          ipv6: "0000:0000:0000:0000:0000:0000:0000:0000",
          cellID: "未知",
          eNBID: "未知",
          tac: "未知",
          csq: "-",
          // rssi: "-",
          rsrpLTE: "-",
          rsrpNR: "-",
          rsrpLTEPercentage: "0%",
          rsrpNRPercentage: "0%",
          rsrqLTE: "-",
          rsrqNR: "-",
          rsrqLTEPercentage: "0%",
          rsrqNRPercentage: "0%",
          sinrLTE: "-",
          sinrNR: "-",
          sinrLTEPercentage: "0%",
          sinrNRPercentage: "0%",
          signalPercentage: "0",
          signalAssessment: "未知",
          uptime: "Unknown",
          lastUpdate: new Date().toLocaleString(),
          newRefreshRate: null,
          refreshRate: 3,
          nrDownload: "0",
          nrUpload: "0",
          nonNrDownload: "0",
          nonNrUpload: "0",
          downloadStat: "0",
          uploadStat: "0",
          mccmncNumber: "未知",
          ambr: "未知",
          qci: "未知",

          fetchAllInfo() {
            this.atcmd =
              'AT+QTEMP;+QUIMSLOT?;+QSPN;+CGCONTRDP=1;+QMAP="WWANIP";+QENG="servingcell";+QCAINFO;+QSIMSTAT?;+CSQ;+QGDNRCNT?;+QGDCNT?;+QNWCFG="nr5g_ambr"';

            fetch(
              "/cgi-bin/get_atcommand?" +
                new URLSearchParams({
                  atcmd: this.atcmd,
                })
            ).then((response) => {
              response.text().then((data) => {
                // content here
                if (data.includes("ERROR")) {
                  console.log("Error fetching data");
                  this.activeSim = "Something went wrong.";
                  return;
                } else {
                  const rawdata = data;
                  const lines = rawdata.split("\n");

                  console.log(lines);

                  // --- Temperature ---
                  // find this example value from lines "+QTEMP:"cpuss-0-usr","50"
                  try {
                    this.temperature = lines
                      .find((line) => line.includes('+QTEMP:"cpuss-0-usr"'))
                      .split(",")[1]
                      .replace(/"/g, "");
                  } catch (error) {
                    this.temperature = lines
                      .find((line) => line.includes('+QTEMP:"cpu0-a7-usr"'))
                      .split(",")[1]
                      .replace(/"/g, "");
                  }

                  // --- SIM Status ---
                  // find this example value from lines "+QSIMSTAT: 0,1"
                  // Only get the last digit of 0,1
                  const sim_status = lines
                    .find((line) => line.includes("+QSIMSTAT:"))
                    .split(" ")[1]
                    .replace(/"/g, "")
                    .split(",")[1];

                  if (sim_status == 1) {
                    this.simStatus = "已激活";
                  } else if (sim_status == 0) {
                    this.simStatus = "无SIM卡";
                  }

                  // --- Active SIM ---
                  // find this example value from lines "+QUIMSLOT: 1"
                  const current_sim = lines
                    .find((line) => line.includes("+QUIMSLOT:"))
                    .split(" ")[1]
                    .replace(/"/g, "");

                  if (current_sim == 1) {
                    this.activeSim = "SIM 1";
                  } else if (current_sim == 2) {
                    this.activeSim = "SIM 2";
                  } else {
                    this.activeSim = "无SIM";
                  }

                  // --- Network Provider ---
                  // find this example value from lines "+QSPN: \"515 66\",\"515 66\",\"DITO\",0,\"51566\""
                  // remove any spaces
                  const network_provider = lines
                    .find((line) => line.includes("+QSPN:"))
                    .split(",")[0]
                    .replace("+QSPN: ", "")
                    .replace(/"/g, "")
                    .replace(/ /g, "");

                  // if network provider is composed of numbers and spaces, and no letters then use .split(",")[2]

                    const mccmncMap = {
                        "46000":"中国移动",
                         "46001":"中国联通",  "46003":"中国电信",  "46009":"中国联通",
                           "46011":"中国电信", "46015":"中国广电", "46020":"中国铁通"};

                  // --- MCCMNC ---
                  this.mccmnc = lines
                    .find((line) => line.includes("+QSPN:"))
                    .split(",")[4]
                    .replace(/"/g, "");

                  const mccmncNumber = Number(this.mccmnc);


                  this.networkProvider = mccmncMap[mccmncNumber] || "未知运营商";


                  // --- APN ---
                  // find this example value from lines "+CGCONTRDP: 1,0,\"internet.dito.ph\",\"100.65.141.236\",\"36.5.141.64.76.204.39.68.23.210.251.16.49.239.42.149\", \"254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1\",\"131.226.72.19\",\"131.226.73.19\"\r"
                  this.apn = lines
                    .find((line) => line.includes("+CGCONTRDP:"))
                    .split(",")[2]
                    .replace(/"/g, "");

                  // --- Network Mode ---
                  // find this example value from lines "+QENG: \"servingcell\",\"NOCONN\",\"NR5G-SA\",\"TDD\",515,66,7000C4001,475,702000,620640,78,12,-83,-3,16,1,-\r"

                  try {
                    const network_mode = lines
                      .find((line) => line.includes('+QENG: "servingcell"'))
                      .split(",")[2]
                      .replace(/"/g, "");

                    const duplex_mode = lines
                      .find((line) => line.includes('+QENG: "servingcell"'))
                      .split(",")[3]
                      .replace(/"/g, "");

                      const network_ambr = lines
                      .find((line) => line.includes('+QNWCFG: "nr5g_ambr"'))
                      .split(",");
                      		this.ambr = network_ambr[3].replace(/"/g, "") + " / " + network_ambr[5].replace(/"/g, "") ;
                          		this.qci = network_ambr[2].replace(/"/g, "");

                    if (network_mode == "NR5G-SA") {
                      if (duplex_mode == "TDD") {
                        this.networkMode = "5G SA TDD";
                      } else if (duplex_mode == "FDD") {
                        this.networkMode = "5G SA FDD";
                      }
                    }

                    if (network_mode == "LTE") {
                      // get the FDD | TDD value
                      const is_tdd = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[3]
                        .replace(/"/g, "");

                      if (is_tdd == "TDD") {
                        this.networkMode = "4G LTE TDD";
                      } else if (is_tdd == "FDD") {
                        this.networkMode = "4G LTE FDD";
                      }
                    }
                  } catch (error) {
                    // find this example value from lines "+QENG: \"LTE\",\"FDD\",515,03,22AE76D,398,1350,3,4,4,BF82,-110,-13,-78,10,6,200,-\r"

                    const network_mode_lte = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[0]
                      .replace("+QENG: ", "")
                      .replace(/"/g, "");

                    try {
                      // find this example value from lines "+QENG: \"NR5G-NSA\",515,03,843,-95,20,-11,528030,41,8,1\r"
                      const network_mode_5g = lines
                        .find((line) => line.includes('+QENG: "NR5G-NSA"'))
                        .split(",")[0]
                        .replace("+QENG: ", "")
                        .replace(/"/g, "");

                      this.networkMode = "5G NSA";
                    } catch (error) {
                      if (network_mode_lte == "FDD") {
                        this.networkMode = "4G LTE FDD";
                      } else if (network_mode_lte == "TDD") {
                        this.networkMode = "4G LTE TDD";
                      }
                    }
                  }

                  // --- Bands ---
                  // Get all the values with LTE BAND n (for example, LTE BAND 3, LTE BAND 1) and then store them in an array
                  const bands = lines.filter((line) =>
                    line.includes("LTE BAND")
                  );

                  // since it includes the whole line, we need to extract the band part only
                  for (let i = 0; i < bands.length; i++) {
                    bands[i] = bands[i].split(",")[3].replace(/"/g, "");
                  }

                  // Get all the values with NR BAND n (for example, NR BAND 3, NR BAND 1) and then store them in an array
                  const bands_5g = lines.filter((line) =>
                    line.includes("NR5G BAND")
                  );

                  // since it includes the whole line, we need to extract the band number only
                  for (let i = 0; i < bands_5g.length; i++) {
                    bands_5g[i] = bands_5g[i].split(",")[3].replace(/"/g, "");
                  }

                  // Combine the bands and bands_5g arrays seperated by a comma. however, bands or bands_5g can be empty
                  if (bands.length > 0 && bands_5g.length > 0) {
                    this.bands = bands.join(", ") + ", " + bands_5g.join(", ");
                  } else if (bands.length > 0) {
                    this.bands = bands.join(", ");
                  } else if (bands_5g.length > 0) {
                    this.bands = bands_5g.join(", ");
                  } else {
                    this.bands = "无频段";
                  }

                  // --- Bandwidth ---
                  if (
                    this.networkMode == "5G SA TDD" ||
                    this.networkMode == "5G SA FDD"
                  ) {
                    // find this example value from lines "+QENG: \"servingcell\"
                    const bandwidth_line = lines.find((line) =>
                      line.includes('+QENG: "servingcell"')
                    );
                    const nr_bw = bandwidth_line.split(",")[11];
                    const calculated_bandwidth = this.calculate_nr_bw(nr_bw);
                    this.bandwidth = "NR " + calculated_bandwidth + " MHz";
                  } else if (
                    this.networkMode == "4G LTE FDD" ||
                    this.networkMode == "4G LTE TDD"
                  ) {
                    // find this example value from lines "+QENG: \"servingcell\"
                    const bandwidth_line = lines.find((line) =>
                      line.includes('+QENG: "servingcell"')
                    );

                    const lte_bw_ul = bandwidth_line.split(",")[10];
                    const lte_bw_dl = bandwidth_line.split(",")[11];
                    const calculated_bandwidth_ul =
                      this.calculate_lte_bw(lte_bw_ul);
                    const calculated_bandwidth_dl =
                      this.calculate_lte_bw(lte_bw_dl);
                    this.bandwidth =
                      calculated_bandwidth_ul +
                      " UL / " +
                      calculated_bandwidth_dl +
                      " DL MHz";
                  } else if (this.networkMode == "5G NSA") {
                    // find this example value from lines "+QENG: \"LTE\" for LTE
                    const lte_bandwidth_line = lines.find((line) =>
                      line.includes('+QENG: "LTE"')
                    );

                    const lte_bw_ul = lte_bandwidth_line.split(",")[8];
                    const lte_bw_dl = lte_bandwidth_line.split(",")[9];

                    const calculated_bandwidth_ul =
                      this.calculate_lte_bw(lte_bw_ul);
                    const calculated_bandwidth_dl =
                      this.calculate_lte_bw(lte_bw_dl);

                    // find this example value from lines "+QENG: \"NR5G-NSA\" for NR5G
                    const nr_bandwidth_line = lines.find((line) =>
                      line.includes('+QENG: "NR5G-NSA"')
                    );

                    const nr_bw = nr_bandwidth_line.split(",")[9];
                    const calculated_bandwidth = this.calculate_nr_bw(nr_bw);

                    // combine the bandwidths
                    this.bandwidth =
                      calculated_bandwidth_ul +
                      " UL / " +
                      calculated_bandwidth_dl +
                      " DL MHz" +
                      " / NR " +
                      calculated_bandwidth +
                      " MHz";
                  } else {
                    this.bandwidth = "未知带宽";
                  }

                  // --- E/ARFCN ---
                  if (
                    this.networkMode == "5G SA TDD" ||
                    this.networkMode == "5G SA FDD"
                  ) {
                    // find this value from lines "+QCAINFO: \"PCC\"
                    const nr_pcc_arfcn = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[1];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const nr_scc_arfcn = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // if empty, then proceed to error block
                      if (nr_scc_arfcn.length == 0) {
                        throw "No SCC ARFCN";
                      }

                      // process all the values in the array and extract the ARFCN part only
                      for (let i = 0; i < nr_scc_arfcn.length; i++) {
                        nr_scc_arfcn[i] = nr_scc_arfcn[i].split(",")[1];
                      }

                      // combine the PCC and SCC ARFCN values
                      this.earfcns =
                        nr_pcc_arfcn + ", " + nr_scc_arfcn.join(", ");
                    } catch (error) {
                      this.earfcns = nr_pcc_arfcn.replace(/,/g, "");
                    }
                  } else if (
                    this.networkMode == "4G LTE FDD" ||
                    this.networkMode == "4G LTE TDD"
                  ) {
                    // find this value from lines "+QCAINFO: \"PCC\"
                    const lte_pcc_arfcn = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[1];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const lte_scc_arfcn = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // if empty, then proceed to error block
                      if (lte_scc_arfcn.length == 0) {
                        throw "No SCC ARFCN";
                      }

                      // process all the values in the array and extract the ARFCN part only
                      for (let i = 0; i < lte_scc_arfcn.length; i++) {
                        lte_scc_arfcn[i] = lte_scc_arfcn[i].split(",")[1];
                      }

                      // combine the PCC and SCC ARFCN values
                      this.earfcns =
                        lte_pcc_arfcn + ", " + lte_scc_arfcn.join(", ");
                    } catch (error) {
                      this.earfcns = lte_pcc_arfcn.replace(/,/g, "");
                    }
                  } else if (this.networkMode == "5G NSA") {
                    // find this value from lines "+QCAINFO: \"PCC\"
                    const lte_pcc_arfcn = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[5];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const lte_scc_arfcn = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // If empty, then proceed to error block
                      if (lte_scc_arfcn.length == 0) {
                        throw "No SCC ARFCN";
                      }

                      // process all the values in the array and extract the ARFCN part only
                      for (let i = 0; i < lte_scc_arfcn.length; i++) {
                        lte_scc_arfcn[i] = lte_scc_arfcn[i].split(",")[1];
                      }

                      // combine the PCC and SCC ARFCN values
                      this.earfcns =
                        lte_pcc_arfcn + ", " + lte_scc_arfcn.join(", ");
                    } catch (error) {
                      this.earfcns = lte_pcc_arfcn.replace(/,/g, "");
                    }
                  } else {
                    this.earfcns = "未知E/ARFCN";
                  }

                  // --- PCI ---
                  if (
                    this.networkMode == "5G SA TDD" ||
                    this.networkMode == "5G SA FDD"
                  ) {
                    const nr_pcc_pci = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[4];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const nr_scc_pci = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // if empty, then proceed to error block
                      if (nr_scc_pci.length == 0) {
                        throw "No SCC PCI";
                      }

                      // process all the values in the array and extract the PCI part only
                      for (let i = 0; i < nr_scc_pci.length; i++) {
                        nr_scc_pci[i] = nr_scc_pci[i].split(",")[5];
                      }

                      // combine the PCC and SCC PCI values
                      this.pccPCI = nr_pcc_pci;
                      this.sccPCI = nr_scc_pci.join(", ");
                    } catch (error) {
                      // remove comma if only one value
                      this.pccPCI = nr_pcc_pci.replace(/,/g, "");
                      this.sccPCI = "-";
                    }
                  } else if (
                    this.networkMode == "4G LTE FDD" ||
                    this.networkMode == "4G LTE TDD"
                  ) {
                    // find this value from lines "+QCAINFO: \"PCC\"
                    const lte_pcc_pci = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[5];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const lte_scc_pci = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // if empty, then proceed to error block
                      if (lte_scc_pci.length == 0) {
                        throw "No SCC PCI";
                      }

                      // process all the values in the array and extract the PCI part only
                      for (let i = 0; i < lte_scc_pci.length; i++) {
                        lte_scc_pci[i] = lte_scc_pci[i].split(",")[5];
                      }

                      // combine the PCC and SCC PCI values
                      this.pccPCI = lte_pcc_pci;
                      this.sccPCI = lte_scc_pci.join(", ");
                    } catch (error) {
                      this.pccPCI = lte_pcc_pci;
                      this.sccPCI = "-";
                    }
                  } else if (this.networkMode == "5G NSA") {
                    // find this value from lines "+QCAINFO: \"PCC\"
                    const lte_pcc_pci = lines
                      .find((line) => line.includes('+QCAINFO: "PCC"'))
                      .split(",")[5];

                    try {
                      // Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
                      const lte_scc_pci = lines.filter((line) =>
                        line.includes('+QCAINFO: "SCC"')
                      );

                      // if empty, then proceed to error block
                      if (lte_scc_pci.length == 0) {
                        throw "No SCC PCI";
                      }

                      // process all the values in the array and extract the PCI part only
                      for (let i = 0; i < lte_scc_pci.length; i++) {
                        // if line contains LTE BAND then do this process
                        if (lte_scc_pci[i].includes("LTE BAND")) {
                          lte_scc_pci[i] = lte_scc_pci[i].split(",")[5];
                        } else {
                          lte_scc_pci[i] = lte_scc_pci[i].split(",")[4];
                        }
                      }

                      // combine the PCC and SCC PCI values
                      this.pccPCI = lte_pcc_pci;
                      this.sccPCI = lte_scc_pci.join(", ");
                    } catch (error) {
                      this.pccPCI = lte_pcc_pci.replace(/,/g, "");
                      this.sccPCI = "-";
                    }
                  } else {
                    this.pccPCI = "0";
                    this.sccPCI = "-";
                  }

                  // --- IPv4 and IPv6 ---
                  // find the value from line "IPV4"
                  this.ipv4 = lines
                    .find((line) => line.includes("IPV4"))
                    .split(",")[4]
                    .replace(/"/g, "");

                  // find the value from line "IPV6"
                  this.ipv6 = lines
                    .find((line) => line.includes("IPV6"))
                    .split(",")[4]
                    .replace(/"/g, "");

                  // Traffic Stats
                  // for NR traffic stats: +QGDNRCNT: 3263753367,109876105
                  this.nrDownload = lines
                    .find((line) => line.includes("+QGDNRCNT:"))
                    .split(",")[0]
                    // remove the +QGDNRCNT: part
                    .replace("+QGDNRCNT: ", "");

                  this.nrUpload = lines
                    .find((line) => line.includes("+QGDNRCNT:"))
                    .split(",")[1];

                  // for non-NR traffic stats: +QGDCNT: 247357510,6864571506
                  this.nonNrDownload = lines
                    .find((line) => line.includes("+QGDCNT:"))
                    .split(",")[1];

                  this.nonNrUpload = lines
                    .find((line) => line.includes("+QGDCNT:"))
                    .split(",")[0]
                    // remove the +QGDCNT: part
                    .replace("+QGDCNT: ", "");

                  // Add the nrDownload and nonNrDownload together
                  this.downloadStat =
                    parseInt(this.nrDownload) + parseInt(this.nonNrDownload);

                  // Add the nrUpload and nonNrUpload together
                  this.uploadStat =
                    parseInt(this.nrUpload) + parseInt(this.nonNrUpload);

                  // Convert the downloadStat and uploadStat bytes to readable size
                  this.downloadStat = this.bytesToSize(this.downloadStat);
                  this.uploadStat = this.bytesToSize(this.uploadStat);

                  console.log(this.downloadStat);
                  console.log(this.uploadStat);

                  // Signal Informations

                  const currentNetworkMode = this.networkMode;

                  if (
                    currentNetworkMode == "5G SA TDD" ||
                    currentNetworkMode == "5G SA FDD" ||
                    currentNetworkMode == "4G LTE FDD" ||
                    currentNetworkMode == "4G LTE TDD"
                  ) {
                    // find the value from line "+QENG: \"servingcell\""
                    // CellID
                    const longCID = lines
                      .find((line) => line.includes('+QENG: "servingcell"'))
                      .split(",")[6]
                      .replace(/"/g, "");

                    // Get the eNBID. Its just Cell ID minus the last 2 characters
                    this.eNBID = longCID.substring(0, longCID.length - 2);

                    // Get the short Cell ID (Last 2 characters of the Cell ID)
                    const shortCID = longCID.substring(longCID.length - 2);

                    if (
                      currentNetworkMode == "5G SA TDD" ||
                      currentNetworkMode == "5G SA FDD"
                    ) {
                      // TAC
                      this.tac = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[8]
                        .replace(/"/g, "");

                      // CSQ
                      this.csq = "NR-SA Mode";

                      // RSRP
                      this.rsrpNR = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[12]
                        .replace(/"/g, "");

                      // RSRQ
                      this.rsrqNR = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[13]
                        .replace(/"/g, "");

                      // SINR
                      this.sinrNR = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[14]
                        .replace(/"/g, "");

                      // Calculate the RSRP Percentage
                      this.rsrpNRPercentage = this.calculateRSRPPercentage(
                        parseInt(this.rsrpNR)
                      );

                      // Calculate the RSRQ Percentage
                      this.rsrqNRPercentage = this.calculateRSRQPercentage(
                        parseInt(this.rsrqNR)
                      );

                      // Calculate the SINR Percentage
                      this.sinrNRPercentage = this.calculateSINRPercentage(
                        parseInt(this.sinrNR)
                      );

                      // Calculate the Signal Percentage
                      this.signalPercentage = this.calculateSignalPercentage(
                        this.rsrpNRPercentage,
                        this.sinrNRPercentage
                      );

                      // Calculate the Signal Assessment
                      this.signalAssessment = this.signalQuality(
                        this.signalPercentage
                      );
                    } else {
                      // LTE Only
                      // TAC
                      this.tac = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[12]
                        .replace(/"/g, "");

                      // CSQ
                      this.csq = lines
                        .find((line) => line.includes("+CSQ:"))
                        .split(" ")[1]
                        .replace("+CSQ: ", "")
                        .replace(/"/g, "");

                      // RSRP
                      this.rsrpLTE = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[13]
                        .replace(/"/g, "");

                      // RSRQ
                      this.rsrqLTE = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[14]
                        .replace(/"/g, "");

                      // // RSSI
                      // this.rssi = lines
                      //   .find((line) => line.includes('+QENG: "servingcell"'))
                      //   .split(",")[15]
                      //   .replace(/"/g, "");

                      // SINR
                      this.sinrLTE = lines
                        .find((line) => line.includes('+QENG: "servingcell"'))
                        .split(",")[16]
                        .replace(/"/g, "");

                      // Calculate the RSRP Percentage
                      this.rsrpLTEPercentage = this.calculateRSRPPercentage(
                        parseInt(this.rsrpLTE)
                      );

                      // Calculate the RSRQ Percentage
                      this.rsrqLTEPercentage = this.calculateRSRQPercentage(
                        parseInt(this.rsrqLTE)
                      );

                      // Calculate the SINR Percentage
                      this.sinrLTEPercentage = this.calculateSINRPercentage(
                        parseInt(this.sinrLTE)
                      );

                      // Calculate the Signal Percentage
                      this.signalPercentage = this.calculateSignalPercentage(
                        this.rsrpLTEPercentage,
                        this.sinrLTEPercentage
                      );

                      // Calculate the Signal Assessment
                      this.signalAssessment = this.signalQuality(
                        this.signalPercentage
                      );
                    }

                    this.cellID =
                      "Short " +
                      shortCID +
                      "(" +
                      parseInt(shortCID, 16) +
                      ")" +
                      ", " +
                      "Long " +
                      longCID +
                      "(" +
                      parseInt(longCID, 16) +
                      ")";
                  } else if (currentNetworkMode == "5G NSA") {
                    // find the value from line "+QENG: \"LTE\" for LTE
                    // LongCID
                    const longCID = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[4]
                      .replace(/"/g, "");

                    // Get the eNBID. Its just Cell ID minus the last 2 characters
                    this.eNBID = longCID.substring(0, longCID.length - 2);

                    // Get the short Cell ID (Last 2 characters of the Cell ID)
                    const shortCID = longCID.substring(longCID.length - 2);

                    // cellID
                    this.cellID =
                      "Short " +
                      shortCID +
                      "(" +
                      parseInt(shortCID, 16) +
                      ")" +
                      ", " +
                      "Long " +
                      longCID +
                      "(" +
                      parseInt(longCID, 16) +
                      ")";

                    // TAC
                    this.tac = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[10]
                      .replace(/"/g, "");

                    // CSQ
                    this.csq = lines
                      .find((line) => line.includes("+CSQ:"))
                      .split(" ")[1]
                      .replace("+CSQ: ", "")
                      .replace(/"/g, "");

                    // RSRP LTE
                    this.rsrpLTE = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[11]
                      .replace(/"/g, "");

                    // RSRQ LTE
                    this.rsrqLTE = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[12]
                      .replace(/"/g, "");

                    // // RSSI LTE
                    // this.rssi = lines
                    //   .find((line) => line.includes('+QENG: "LTE"'))
                    //   .split(",")[13]
                    //   .replace(/"/g, "");

                    // SINR LTE
                    this.sinrLTE = lines
                      .find((line) => line.includes('+QENG: "LTE"'))
                      .split(",")[14]
                      .replace(/"/g, "");

                    // Calculate the RSRP LTE Percentage
                    this.rsrpLTEPercentage = this.calculateRSRPPercentage(
                      parseInt(this.rsrpLTE)
                    );

                    // Calculate the RSRQ LTE Percentage
                    this.rsrqLTEPercentage = this.calculateRSRQPercentage(
                      parseInt(this.rsrqLTE)
                    );

                    // Calculate the SINR LTE Percentage
                    this.sinrLTEPercentage = this.calculateSINRPercentage(
                      parseInt(this.sinrLTE)
                    );

                    // Calculate the Signal Percentage
                    const lte_signal_percentage =
                      this.calculateSignalPercentage(
                        this.rsrpLTEPercentage,
                        this.sinrLTEPercentage
                      );

                    // find the value from line "+QENG: \"NR5G-NSA\" for NR5G
                    // RSRP NR
                    this.rsrpNR = lines
                      .find((line) => line.includes('+QENG: "NR5G-NSA"'))
                      .split(",")[4]
                      .replace(/"/g, "");

                    // SINR NR
                    this.sinrNR = lines
                      .find((line) => line.includes('+QENG: "NR5G-NSA"'))
                      .split(",")[5]
                      .replace(/"/g, "");

                    // RSRQ NR
                    this.rsrqNR = lines
                      .find((line) => line.includes('+QENG: "NR5G-NSA"'))
                      .split(",")[6]
                      .replace(/"/g, "");

                    // Calculate the RSRP NR Percentage
                    this.rsrpNRPercentage = this.calculateRSRPPercentage(
                      parseInt(this.rsrpNR)
                    );

                    // Calculate the RSRQ NR Percentage
                    this.rsrqNRPercentage = this.calculateRSRQPercentage(
                      parseInt(this.rsrqNR)
                    );

                    // Calculate the SINR NR Percentage
                    this.sinrNRPercentage = this.calculateSINRPercentage(
                      parseInt(this.sinrNR)
                    );

                    // Calculate the Signal Percentage
                    const nr_signal_percentage = this.calculateSignalPercentage(
                      this.rsrpNRPercentage,
                      this.sinrNRPercentage
                    );

                    // Average the LTE and NR Signal Percentages
                    this.signalPercentage =
                      (lte_signal_percentage + nr_signal_percentage) / 2;

                    // Calculate the Signal Assessment
                    this.signalAssessment = this.signalQuality(
                      this.signalPercentage
                    );
                  } else {
                    this.signalAssessment = "No Signal";
                  }
                }
              });
            });
          },

          bytesToSize(bytes) {
            const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
            if (bytes == 0) return "0 Byte";
            const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
            return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i];
          },

          requestPing() {
            return fetch("/cgi-bin/get_ping")
              .then((response) => response.text())
              .then((data) => {
                return data;
              })
              .catch((error) => {
                console.error("Error:", error);
                // Throw the error again to ensure it's propagated
                throw error;
              });
          },

          calculate_lte_bw(lte_bw) {
            switch (true) {
              case 0:
                return 1.4;
              case 1:
                return 3;
              // Now case 2 - 5
              case lte_bw >= 2 && lte_bw <= 5:
                return (lte_bw - 1) * 5;
              default:
                return "未知";
            }
          },

          calculate_nr_bw(nr_bw) {
            switch (true) {
              case nr_bw >= 0 && nr_bw <= 5:
                return (nr_bw + 1) * 5;
              case nr_bw >= 6 && nr_bw <= 12:
                return (nr_bw - 2) * 10;
              case nr_bw === 13:
                return "200";
              case nr_bw === 14:
                return "400";
              default:
                return "未知";
            }
          },

          calculateRSRPPercentage(rsrp) {
            let RSRP_min = -135;
            let RSRP_max = -65;

            // If rsrp is null, return 0%
            if (isNaN(rsrp) || rsrp < -140) {
              return 0;
            }

            let percentage = ((rsrp - RSRP_min) / (RSRP_max - RSRP_min)) * 100;

            if (percentage > 100) {
              percentage = 100;
            }

            // if percentage is less than 15%, make it 15%
            if (percentage < 15) {
              percentage = 15;
            }

            return Math.round(percentage);
          },

          calculateRSRQPercentage(rsrq) {
            let RSRQ_min = -20;
            let RSRQ_max = -8;

            // If rsrq is null, return 0%
            if (isNaN(rsrq) || rsrq < -20) {
              return 0;
            }

            let percentage = ((rsrq - RSRQ_min) / (RSRQ_max - RSRQ_min)) * 100;

            if (percentage > 100) {
              percentage = 100;
            }

            // if percentage is less than 15%, make it 15%
            if (percentage < 15) {
              percentage = 15;
            }

            return Math.round(percentage);
          },

          calculateSINRPercentage(sinr) {
            let SINR_min = -10; // Changed from 0
            let SINR_max = 35;

            // If sinr is null, return 0%
            if (isNaN(sinr) || sinr < -10) {
              return 0;
            }

            let percentage = ((sinr - SINR_min) / (SINR_max - SINR_min)) * 100;

            if (percentage > 100) {
              percentage = 100;
            }

            // if percentage is less than 15%, make it 15%
            if (percentage < 15) {
              percentage = 15;
            }

            return Math.round(percentage);
          },

          // Calculate the overall signal assessment
          calculateSignalPercentage(rsrpNRPercentage, sinrNRPercentage) {
            // Get the average of the RSRP Percentage and SINR Percentage
            let average = (rsrpNRPercentage + sinrNRPercentage) / 2;
            return Math.round(average);
          },

          signalQuality(percentage) {
            if (percentage >= 80) {
              return "优秀";
            } else if (percentage >= 60) {
              return "良好";
            } else if (percentage >= 40) {
              return "一般";
            } else if (percentage >= 0) {
              return "差";
            } else {
              return "无信号";
            }
          },

          fetchUpTime() {
            // Content-Type: text/plain
            //
            // 1 hour 44, minute
            fetch("/cgi-bin/get_uptime")
              .then((response) => response.text())
              .then((data) => {
                // Example result
                // 01:17:02 up 3 days,  2:41,  load average: 0.65, 0.66, 0.60

                // Look for xx days in the result
                const days = data.match(/(\d+) day/);
                // Do the same for hours
                const hours = data.match(/(\d+) hour/);
                // Do the same for minutes
                const minutes = data.match(/(\d+) min/);
                // 2:41
                const hoursAndMinutes = data.match(/(\d+):(\d+),/);

                if (hoursAndMinutes != null) {
                  if (days != null) {
                    if (days[1] === "1") {
                      if (hoursAndMinutes[1] === "1") {
                        this.uptime =
                          days[1] +
                          " day, " +
                          hoursAndMinutes[1] +
                          " hour " +
                          hoursAndMinutes[2] +
                          " minutes";
                      } else if (hoursAndMinutes[2] === 1) {
                        this.uptime =
                          days[1] +
                          " day, " +
                          hoursAndMinutes[1] +
                          " hours " +
                          hoursAndMinutes[2] +
                          " minute";
                      } else {
                        this.uptime =
                          days[1] +
                          " day, " +
                          hoursAndMinutes[1] +
                          " hours " +
                          hoursAndMinutes[2] +
                          " minutes";
                      }
                    } else {
                      if (hoursAndMinutes[1] === "1") {
                        this.uptime =
                          days[1] +
                          " days, " +
                          hoursAndMinutes[1] +
                          " hour " +
                          hoursAndMinutes[2] +
                          " minutes";
                      } else if (hoursAndMinutes[2] === 1) {
                        this.uptime =
                          days[1] +
                          " days, " +
                          hoursAndMinutes[1] +
                          " hours " +
                          hoursAndMinutes[2] +
                          " minute";
                      } else {
                        this.uptime =
                          days[1] +
                          " days, " +
                          hoursAndMinutes[1] +
                          " hours " +
                          hoursAndMinutes[2] +
                          " minutes";
                      }
                    }
                  } else {
                    if (hoursAndMinutes[1] === "1") {
                      this.uptime =
                        hoursAndMinutes[1] +
                        " hour " +
                        hoursAndMinutes[2] +
                        " minutes";
                    } else if (hoursAndMinutes[2] === 1) {
                      this.uptime =
                        hoursAndMinutes[1] +
                        " hours " +
                        hoursAndMinutes[2] +
                        " minute";
                    } else {
                      this.uptime =
                        hoursAndMinutes[1] +
                        " hours " +
                        hoursAndMinutes[2] +
                        " minutes";
                    }
                  }
                } else if (days != null) {
                  if (hours != null) {
                    if (days[1] === "1") {
                      if (hours[1] === "1") {
                        this.uptime = days[1] + " day, " + hours[1] + " hour";
                      } else {
                        this.uptime = days[1] + " day, " + hours[1] + " hours";
                      }
                    } else {
                      if (hours[1] === "1") {
                        this.uptime = days[1] + " days, " + hours[1] + " hour";
                      } else {
                        this.uptime = days[1] + " days, " + hours[1] + " hours";
                      }
                    }
                  } else if (minutes != null) {
                    if (days[1] === "1") {
                      if (minutes[1] === "1") {
                        this.uptime =
                          days[1] + " day, " + minutes[1] + " minute";
                      } else {
                        this.uptime =
                          days[1] + " day, " + minutes[1] + " minutes";
                      }
                    } else {
                      if (minutes[1] === "1") {
                        this.uptime =
                          days[1] + " days, " + minutes[1] + " minute";
                      } else {
                        this.uptime =
                          days[1] + " days, " + minutes[1] + " minutes";
                      }
                    }
                  } else {
                    if (days[1] === "1") {
                      this.uptime = days[1] + " day";
                    } else {
                      this.uptime = days[1] + " days";
                    }
                  }
                } else if (hours != null) {
                  if (hours[1] === "1") {
                    this.uptime = hours[1] + " hour";
                  } else {
                    this.uptime = hours[1] + " hours";
                  }
                } else if (minutes != null) {
                  if (minutes[1] === "1") {
                    this.uptime = minutes[1] + " minute";
                  } else {
                    this.uptime = minutes[1] + " minutes";
                  }
                } else {
                  this.uptime = "未知时间";
                }
              });
          },

          updateRefreshRate() {
            // Check if the refresh rate is less than 3
            if (this.newRefreshRate < 3) {
              this.newRefreshRate = 3;
            }

            // Clear the old interval
            clearInterval(this.intervalId);

            // Set the refresh rate
            this.refreshRate = this.newRefreshRate;
            console.log("Refresh Rate Updated to " + this.refreshRate);

            // Store the refresh rate in local storage or session storage
            localStorage.setItem("refreshRate", this.refreshRate);

            // Initialize with the new refresh rate
            this.init();
          },

          init() {
            // Fetch uptime
            this.fetchUpTime();

            // Retrieve the refresh rate from local storage or session storage
            const storedRefreshRate = localStorage.getItem("refreshRate");

            // If a refresh rate is stored, use it; otherwise, use a default value
            this.refreshRate = storedRefreshRate
              ? parseInt(storedRefreshRate)
              : 3; // Change 3 to your desired default value

            this.fetchAllInfo();

            this.requestPing()
              .then((data) => {
                const response = data.trim();
                // Trim any leading/trailing spaces
                if (response === "OK") {
                  this.internetConnectionStatus = "已连接";
                } else {
                  this.internetConnectionStatus = "已断开";
                }
              })
              .catch((error) => {
                console.error("Error:", error);
                this.internetConnectionStatus = "已断开";
              });

            this.lastUpdate = new Date().toLocaleString();
            console.log("Initialized");

            // Set the refresh rate for interval
            this.intervalId = setInterval(() => {
              this.fetchUpTime();

              this.fetchAllInfo();

              this.requestPing()
                .then((data) => {
                  const response = data.trim();
                  // Trim any leading/trailing spaces
                  if (response === "OK") {
                    this.internetConnection = "已连接";
                  } else {
                    this.internetConnection = "已断开";
                  }
                })
                .catch((error) => {
                  console.error("Error:", error);
                  this.internetConnection = "已断开";
                });

              this.lastUpdate = new Date().toLocaleString();
              console.log("Refreshed");
            }, this.refreshRate * 1000);
          },
        };
      }
    </script>
  </body>
</html>